/*!
\copyright  Copyright (c) 2023 Qualcomm Technologies International, Ltd.\n
            All Rights Reserved.\n
            Qualcomm Technologies International, Ltd. Confidential and Proprietary.
\version    
\file       
\brief      Procedure to connect the DFU version Share Profile between the earbuds.
*/

#ifdef INCLUDE_CROSS_VERSION_DFU
#include "tws_topology_procedure_dfu_version_share.h"
#include "tws_topology_procedures.h"
#include "tws_topology_private.h"
#include "tws_topology_config.h"

#include "multidevice.h"
#include <bt_device.h>
#include <dfu_version_share_profile.h>
#include <connection_manager.h>

#include <logging.h>
#include <message.h>
#include "upgrade.h"
#include "earbud_sm.h"

static void twsTopology_ProcDfuVersionShareProfileHandleMessage(Task task, MessageId id, Message message);
void TwsTopology_ProcedureDfuVersionShareProfileStart(Task result_task,
                                        procedure_start_cfm_func_t proc_start_cfm_fn,
                                        procedure_complete_func_t proc_complete_fn,
                                        Message goal_data);
void TwsTopology_ProcedureDfuVersionShareProfileCancel(procedure_cancel_cfm_func_t proc_cancel_fn);

const procedure_fns_t proc_dfu_version_share_profile_fns = {
    TwsTopology_ProcedureDfuVersionShareProfileStart,
    TwsTopology_ProcedureDfuVersionShareProfileCancel,
};

typedef struct
{
    TaskData task;
    procedure_complete_func_t complete_fn;
    bool active;
} twsTopProcDfuVersionShareProfileTaskData;

twsTopProcDfuVersionShareProfileTaskData twstop_proc_connect_dfu_version_share_profile = { .task = {twsTopology_ProcDfuVersionShareProfileHandleMessage}, .complete_fn = NULL, .active = FALSE};

#define TwsTopProcDfuVersionShareProfileGetTaskData()     (&twstop_proc_connect_dfu_version_share_profile)
#define TwsTopProcDfuVersionShareProfileGetTask()         (&twstop_proc_connect_dfu_version_share_profile.task)

static void twsTopology_ProcedureDfuVersionShareProfileReset(void)
{
    DEBUG_LOG_DEBUG("twsTopology_ProcedureDfuVersionShareProfileReset");
    twsTopProcDfuVersionShareProfileTaskData* td = TwsTopProcDfuVersionShareProfileGetTaskData();
    appPowerPerformanceProfileRelinquish();
    td->active = FALSE;
}

void TwsTopology_ProcedureDfuVersionShareProfileStart(Task result_task,
                                                   procedure_start_cfm_func_t proc_start_cfm_fn,
                                                   procedure_complete_func_t proc_complete_fn,
                                                   Message goal_data)
{
    twsTopProcDfuVersionShareProfileTaskData* td = TwsTopProcDfuVersionShareProfileGetTaskData();

    UNUSED(result_task);
    UNUSED(goal_data);
    UNUSED(proc_start_cfm_fn);

    appPowerPerformanceProfileRequest();

    /* remember completion function */
    td->complete_fn = proc_complete_fn;
    /* mark procedure active so if cleanup() requested this procedure can ignore
     * any CFM messages that arrive afterwards */
    td->active = TRUE;

    DEBUG_LOG_DEBUG("TwsTopology_ProcedureDfuVersionShareProfileStart DFU VERSION SHARE CONNECT");
    DfuVersionShareProfile_GetVersion(TwsTopProcDfuVersionShareProfileGetTask());
}

void TwsTopology_ProcedureDfuVersionShareProfileCancel(procedure_cancel_cfm_func_t proc_cancel_cfm_fn)
{
    DEBUG_LOG_DEBUG("TwsTopology_ProcedureDfuVersionShareProfileCancel");

    twsTopology_ProcedureDfuVersionShareProfileReset();
    Procedures_DelayedCancelCfmCallback(proc_cancel_cfm_fn, tws_topology_procedure_dfu_version_share, procedure_result_success);
}

static void twsTopology_ProcDfuVersionShareProfileHandleMessage(Task task, MessageId id, Message message)
{
    twsTopProcDfuVersionShareProfileTaskData* td = TwsTopProcDfuVersionShareProfileGetTaskData();

    UNUSED(task);

    /* if no longer active then ignore any CFM messages,
     * they'll be connect_cfm(cancelled) */
    if (!td->active)
    {
        return;
    }
    DFU_VERSION_SHARE_PROFILE_VERSION_COMPARISON_RESULT_T *version_message = (DFU_VERSION_SHARE_PROFILE_VERSION_COMPARISON_RESULT_T *)message;

    /* NOTE : FOR ALL FAILURE AND TIMEOUTs WE ARE PROCEEDING AHEAD IN TOPOLOGY AS SUCCESS,
      OTHER SOLUTIONS INVOLVING OF PANICs CAN CAUSE THE DEVICE TO STAY IN PANIC LOOP*/
    switch (id)
    {

        case DFU_VERSION_SHARE_PROFILE_ERROR:
            DEBUG_LOG_DEBUG("twsTopology_ProcDfuVersionShareProfileHandleMessage ERROR %d",version_message->dfu_version_comparison_result);
            twsTopology_ProcedureDfuVersionShareProfileReset();
            /* Save the result of version comparison */
            UpgradeSetCrossVersionStatus(version_message->dfu_version_comparison_result);
            td->complete_fn(tws_topology_procedure_dfu_version_share, procedure_result_success);
        break;

        case DFU_VERSION_SHARE_PROFILE_COMPARISON_RESULT:
            DEBUG_LOG_INFO("twsTopology_ProcDfuVersionShareProfileHandleMessage COMPARISON_RESULT :%d", 
                    version_message->dfu_version_comparison_result);
            twsTopology_ProcedureDfuVersionShareProfileReset();
            
            /* Save the result of version comparison */
            UpgradeSetCrossVersionStatus(version_message->dfu_version_comparison_result);
            td->complete_fn(tws_topology_procedure_dfu_version_share, procedure_result_success);
        break;

        default:
        break;
    }
}

#define DFU_VERSION_SHARE_SCRIPT(ENTRY) \
    ENTRY(proc_dfu_version_share_profile_fns, NO_DATA)

/* Define the dfu_version_share_script */
DEFINE_TOPOLOGY_SCRIPT(dfu_version_share, DFU_VERSION_SHARE_SCRIPT);

#endif //#ifdef INCLUDE_CROSS_VERSION_DFU